import 'dart:convert';
import 'package:http/http.dart' as http;

class TTSService {
  static const String baseUrl = 'http://192.168.100.119:9966';
  static const String ttsEndpoint = '/tts';
  
  static const String defaultPrompt = '[oral_5]';
  static const String defaultVoice = '125.pt';
  static const int defaultSpeed = 4;
  static const double defaultTemperature = 0.1;
  static const double defaultTopP = 0.701;
  static const int defaultTopK = 20;
  static const int defaultRefineMaxNewToken = 384;
  static const int defaultInferMaxNewToken = 2048;
  static const int defaultTextSeed = 42;
  static const int defaultSkipRefine = 1;
  static const int defaultIsStream = 0;
  static const int defaultCustomVoice = 61;

  final http.Client _httpClient;

  TTSService({http.Client? httpClient}) : _httpClient = httpClient ?? http.Client();

  Future<TTSResponse> generateSpeech(String text) async {
    try {
      print('[TTS] 开始生成语音...');
      print('[TTS] URL: $baseUrl$ttsEndpoint');
      print('[TTS] 文本长度: ${text.length}');
      print('[TTS] 文本内容: ${text.length > 50 ? text.substring(0, 50) + '...' : text}');
      
      final requestBody = {
        'text': text,
        'prompt': defaultPrompt,
        'voice': defaultVoice,
        'speed': defaultSpeed.toString(),
        'temperature': defaultTemperature.toString(),
        'top_p': defaultTopP.toString(),
        'top_k': defaultTopK.toString(),
        'refine_max_new_token': defaultRefineMaxNewToken.toString(),
        'infer_max_new_token': defaultInferMaxNewToken.toString(),
        'text_seed': defaultTextSeed.toString(),
        'skip_refine': defaultSkipRefine.toString(),
        'is_stream': defaultIsStream.toString(),
        'custom_voice': defaultCustomVoice.toString(),
      };
      
      print('[TTS] 请求参数: voice=$defaultVoice, speed=$defaultSpeed, temperature=$defaultTemperature');
      
      final startTime = DateTime.now();
      final response = await _httpClient.post(
        Uri.parse('$baseUrl$ttsEndpoint'),
        body: requestBody,
      );
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      
      print('[TTS] 请求完成，耗时: ${duration}ms');
      print('[TTS] 状态码: ${response.statusCode}');
      print('[TTS] 响应体: ${response.body}');

      if (response.statusCode == 200) {
        final jsonResponse = json.decode(response.body);
        final ttsResponse = TTSResponse.fromJson(jsonResponse);
        
        if (ttsResponse.isSuccess) {
          print('[TTS] 语音生成成功，音频文件数量: ${ttsResponse.audioFiles.length}');
          if (ttsResponse.audioFiles.isNotEmpty) {
            print('[TTS] 音频URL: ${ttsResponse.audioFiles.first.url}');
          }
        } else {
          print('[TTS] 业务错误 - code: ${ttsResponse.code}, msg: ${ttsResponse.msg}');
        }
        
        return ttsResponse;
      } else {
        print('[TTS] HTTP错误: ${response.statusCode}');
        throw TTSException('Failed to generate speech: ${response.statusCode}');
      }
    } catch (e) {
      print('[TTS] 生成语音失败: $e');
      print('[TTS] 错误类型: ${e.runtimeType}');
      if (e is TTSException) {
        rethrow;
      }
      throw TTSException('Network error: $e');
    }
  }


  void dispose() {
    _httpClient.close();
  }
}

class TTSResponse {
  final int code;
  final String msg;
  final List<AudioFile> audioFiles;

  TTSResponse({
    required this.code,
    required this.msg,
    required this.audioFiles,
  });

  bool get isSuccess => code == 0;

  factory TTSResponse.fromJson(Map<String, dynamic> json) {
    List<AudioFile> files = [];
    if (json['audio_files'] != null) {
      files = (json['audio_files'] as List)
          .map((file) => AudioFile.fromJson(file))
          .toList();
    }

    return TTSResponse(
      code: json['code'] ?? 1,
      msg: json['msg'] ?? '',
      audioFiles: files,
    );
  }
}

class AudioFile {
  final String filename;
  final String url;

  AudioFile({
    required this.filename,
    required this.url,
  });

  factory AudioFile.fromJson(Map<String, dynamic> json) {
    return AudioFile(
      filename: json['filename'] ?? '',
      url: json['url'] ?? '',
    );
  }
}

class TTSException implements Exception {
  final String message;

  TTSException(this.message);

  @override
  String toString() => 'TTSException: $message';
}